package com.wm.blog_web.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wm.blog_common.base.BeanUtils;
import com.wm.blog_common.bean.PageHelper;
import com.wm.blog_common.bean.QueryPage;
import com.wm.blog_common.constatnt.ErrorConstant;
import com.wm.blog_common.domain.TCommentDO;
import com.wm.blog_common.entity.TBlog;
import com.wm.blog_common.entity.TComment;
import com.wm.blog_common.entity.TUser;
import com.wm.blog_common.enums.CommentFlag;
import com.wm.blog_common.enums.CommentTypeEnum;
import com.wm.blog_common.enums.DeleteFlag;
import com.wm.blog_common.exception.BusinessException;
import com.wm.blog_common.resp.CommentItem;
import com.wm.blog_common.result.Result;
import com.wm.blog_common.util.CommonUtil;
import com.wm.blog_common.util.DateUtil;
import com.wm.blog_web.dao.TBlogDAO;
import com.wm.blog_web.dao.TCommentDAO;
import com.wm.blog_web.dao.TUserDAO;
import com.wm.blog_web.query.TBlogQuery;
import com.wm.blog_web.query.TCommentQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * <p>
 * 评论表 服务实现类
 * </p>
 *
 * @author 半卷流年
 * @since 2020-03-24
 */
@Service
@Slf4j
public class TCommentService {

    @Autowired
    private TCommentDAO tCommentDAO;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private TBlogDAO tBlogDAO;

    @Autowired
    private TUserDAO tUserDAO;

    /**
     * 根据ID查询
     *
     * @param id
     * @return
     */
    public Result<TCommentDO> selectById(Long id) {
        return Result.success(BeanUtils.copyProperties(tCommentDAO.getById(id), TCommentDO.class));
    }

    /**
     * 根据ID删除
     *
     * @param id
     * @return
     */
    public Result deleteById(Long id) {
        return tCommentDAO.removeById(id) ? Result.success() : Result.failure();
    }

    /**
     * 添加
     *
     * @param tComment
     * @return
     */
    public Result insert(TComment tComment) {
        return tCommentDAO.save(tComment) ? Result.success() : Result.failure();
    }

    /**
     * 修改
     *
     * @param tComment
     * @return
     */
    public Result update(TComment tComment) {
        return tCommentDAO.updateById(tComment) ? Result.success() : Result.failure();
    }

    /**
     * 统计总数
     *
     * @param query
     * @return
     */
    public Result<Integer> count(TCommentQuery query) {
        return Result.success(tCommentDAO.count(this.combineQuery(query)));
    }

    /**
     * 列表查询
     *
     * @param query
     * @return
     */
    public Result<List<TCommentDO>> list(TCommentQuery query) {
        return Result.success(BeanUtils.copyListProperties(tCommentDAO.list(this.combineQuery(query)), TCommentDO.class));
    }

    /**
     * 分页查询
     *
     * @param page
     * @return
     */
    public Result page(QueryPage page, TCommentQuery query) {
        /**
         * 1.如果传入的博客id为空,是给我留言的评论
         * 2.传入的博客id不为空,是对应博客的评论
         */query.setIsFirst(true);
        query.setStatus(DeleteFlag.ENABLE.getValue());
        query.setType(CommentFlag.COMMENT.getValue());
        //分页查询一级评论
        IPage<TComment> resultPage = tCommentDAO.commentPage(page, query);
        if (!ObjectUtils.isEmpty(resultPage) && !CollectionUtils.isEmpty(resultPage.getRecords())) {
            List<TComment> firstComment = resultPage.getRecords();
            //查询所有的非一级评论
            query.setIsFirst(false);
            List<TComment> commentList = queryCommentList(query);
            //构建评论树
            //所有的userId和toUserId
            List<TComment> list = new ArrayList<>();
            list.addAll(firstComment);
            list.addAll(commentList);
            List<Long> tempList = new ArrayList<>();
            list.forEach(item -> {
                if (!ObjectUtils.isEmpty(item.getUserId())) {
                    tempList.add(item.getUserId());
                }
                if (!ObjectUtils.isEmpty(item.getToUserId())) {
                    tempList.add(item.getToUserId());
                }
            });
            List<Long> idList = tempList.stream().distinct().collect(Collectors.toList());
            //k:id v:nickName
            Map<Long, TUser> userMap = Optional
                    .ofNullable(tUserDAO.listByIds(idList))
                    .orElse(Collections.emptyList())
                    .stream()
                    .collect(Collectors.toMap(TUser::getId, v -> v));
            List<CommentItem> itemList = CommonUtil.dealComment(firstComment, commentList, userMap);
            return Result.success(itemList);
        }
        return Result.success(Collections.EMPTY_LIST);

    }


    private List<TComment> queryCommentList(TCommentQuery query) {
        QueryWrapper<TComment> wrapper = this.combineQuery(query);
        wrapper.eq("type", CommentFlag.COMMENT.getValue());
        wrapper.eq("status", DeleteFlag.ENABLE.getValue());
        if (!ObjectUtils.isEmpty(query.getBlogId())) {
            wrapper.eq("blog_id", query.getBlogId());
        }
        if (query.getIsFirst()) {
            wrapper.eq("to_id", 0);
        } else {
            wrapper.ne("to_id", 0);
        }
        return Optional
                .ofNullable(tCommentDAO.list(wrapper))
                .orElse(Collections.emptyList());
    }


    /**
     * 组装查询条件
     *
     * @param query
     * @return
     */
    private QueryWrapper<TComment> combineQuery(TCommentQuery query) {
        QueryWrapper<TComment> wrapper = new QueryWrapper<>();
        return wrapper;
    }


    /**
     * 博客点赞
     *
     * @param query
     * @return
     */
    public Result likeBlog(TBlogQuery query) {
        Optional.ofNullable(query.getUserId()).orElseThrow(() -> new BusinessException(ErrorConstant.USER_ID_EMPTY));
        Optional.ofNullable(query.getBlogId()).orElseThrow(() -> new BusinessException(ErrorConstant.BLOG_ID_EMPTY));
        if (query.getUserId().equals(query.getToUserId())) {
            return Result.failure(ErrorConstant.BLOG_LIKE_REPEAT);
        }
        if (-1 == query.getUserId()) {
            return Result.failure(ErrorConstant.USER_NO_LOGIN);
        }
        //一个用户对相同的博客一天只能点赞一次
        QueryWrapper<TComment> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", query.getToUserId());
        wrapper.eq("blog_id", query.getBlogId());
        wrapper.apply("DATE(create_time) = CURDATE()");
        wrapper.eq("type", CommentFlag.LIKE.getValue());
        TComment oldComment = Optional.ofNullable(tCommentDAO.getOne(wrapper)).orElse(new TComment());
        if (!ObjectUtils.isEmpty(oldComment.getId())) {
            return Result.failure(ErrorConstant.BLOG_LIKE_TODAY_ERROR);
        }
        /**
         * 1.新增一条点赞记录
         * 2.推送消息给博客作者,有人对你的博客进行了点赞
         */
        TBlog blog = Optional.ofNullable(tBlogDAO.getById(query.getBlogId())).orElse(new TBlog());
        //新增点赞记录
        CompletableFuture.supplyAsync((() -> {
            TComment comment = new TComment();
            Date now = DateUtil.getCurrentDate();
            comment.setSource(blog.getArticlesPart());
            //评论人id
            comment.setUserId(query.getToUserId());
            comment.setToUserId(query.getToUserId());
            comment.setBlogId(query.getBlogId());
            comment.setStatus(DeleteFlag.ENABLE.getValue());
            comment.setType(CommentTypeEnum.LIKE.getValue());
            boolean save = tCommentDAO.save(comment);
            log.info("新增点赞记录:{}", save);
            return save;
        }), threadPoolTaskExecutor).thenAccept(item -> {
            //推送消息 todo
            if (item) {
                //查询用户信息
                List<Long> idList = new ArrayList<Long>() {{
                    add(query.getUserId());
                    add(query.getToUserId());
                }};
                // k:id v:username
                Map<Long, String> nameMap = Optional
                        .ofNullable(tUserDAO.listByIds(idList))
                        .orElse(Collections.emptyList())
                        .stream()
                        .collect(Collectors.toMap(TUser::getId, TUser::getUserName));
                //查询博客标题
                log.info(String.format("接收消息人:%s,推送文案:%s对你的博客%s进行了点赞,快去看看吧^-^", nameMap.getOrDefault(query.getUserId(), null), nameMap.getOrDefault(query.getToUserId(), null), blog.getTitle()));
            }
        });
        return Result.success();
    }


    /**
     * 发表评论
     *
     * @return
     */
    public Result publishComment(TCommentQuery query) {
        if (query.getUserId().equals(-1L)) {
            return Result.failure(ErrorConstant.USER_NO_LOGIN);
        }
        /**
         * 1.发表评论
         * 2.推送消息给被评论者
         * 3.博客id为空,是给我的评论留言
         * 4.博客id不为空,是给某篇博客的评论
         */
        TBlog blog = Optional.ofNullable(tBlogDAO.getById(query.getBlogId())).orElse(new TBlog());
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            TComment comment = new TComment();
            //评论人id
            comment.setUserId(query.getToUserId());
            comment.setBlogId(query.getBlogId());
            comment.setContent(query.getContent());
            comment.setToUserId(query.getToUserId());
            comment.setStatus(DeleteFlag.ENABLE.getValue());
            comment.setType(CommentTypeEnum.COMMENT.getValue());
            comment.setSource(query.getSource());
            //回复某人的评论
            comment.setToId(query.getToId());
            boolean save = tCommentDAO.save(comment);
            log.info("新增评论记录:{}", save);
            return save;
        }, threadPoolTaskExecutor).thenAccept(item -> {
            //推送消息
            //查询用户信息
            List<Long> idList = new ArrayList<Long>() {{
                add(query.getUserId());
                add(query.getToUserId());
            }};
            // k:id v:username
            Map<Long, String> nameMap = Optional
                    .ofNullable(tUserDAO.listByIds(idList))
                    .orElse(Collections.emptyList())
                    .stream()
                    .collect(Collectors.toMap(TUser::getId, TUser::getUserName));
            log.info(String.format("接收消息人:%s,推送文案:%s对你的博客%s进行了评论,快去看看吧^-^", nameMap.getOrDefault(query.getUserId(), null), nameMap.getOrDefault(query.getToUserId(), null), blog.getTitle()));
        });
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            log.error("线程执行发布评论异常:{}", e.getMessage(), e);
        }
        return Result.success();
    }


    /**
     * 查询点赞量
     *
     * @param query
     * @return
     */
    public Result likeCount(TCommentQuery query) {
        query = Optional.ofNullable(query).orElse(new TCommentQuery());
        Optional.ofNullable(query.getBlogId()).orElseThrow(() -> new BusinessException(ErrorConstant.BLOG_ID_EMPTY));
        QueryWrapper<TComment> wrapper = new QueryWrapper<>();
        wrapper.eq("blog_id", query.getBlogId());
        wrapper.eq("status", DeleteFlag.ENABLE.getValue());
        wrapper.eq("type", CommentFlag.LIKE.getValue());
        return Result.success(tCommentDAO.count(wrapper));
    }
}







